﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;

namespace Ict.DataAccess.Linq
{
    /// <summary>
    /// 查询类基类
    /// </summary>
    public abstract class SelectableBase : IOrderedQueryable
    {
        #region IQueryable 成员

        public abstract Type ElementType
        {
            get;
        }

        public Expression Expression
        {
            get { return System.Linq.Expressions.Expression.Constant(this); }
        }

        public abstract IQueryProvider Provider
        {
            get;
        }

        #endregion

        #region IEnumerable 成员

        public abstract System.Collections.IEnumerator GetEnumerator();

        #endregion

        #region 存储查询表达式

        private LambdaExpression selectClause;

        internal LambdaExpression SelectClause
        {
            get
            {
                return selectClause;
            }
            set
            {
                selectClause = value;
            }
        }

        private List<Expression> whereClause = null;

        internal List<Expression> WhereClause
        {
            get
            {
                if (whereClause == null)
                    whereClause = new List<Expression>();
                return whereClause;
            }
            set
            {
                whereClause = value;
            }
        }

        private List<Expression> orderClause = null;

        internal List<Expression> OrderClause
        {
            get
            {
                if (orderClause == null)
                    orderClause = new List<Expression>();
                return orderClause;
            }
            set
            {
                orderClause = value;
            }
        }

        private bool _isCountOnly = false;
        /// <summary>
        /// 是否仅需返回记录数
        /// </summary>
        public bool IsCountOnly
        {
            get
            {
                return _isCountOnly;
            }
            set
            {
                _isCountOnly = value;
            }
        }

        private int takeCount = 0;

        internal int TakeCount
        {
            get
            {
                return takeCount;
            }
            set
            {
                takeCount = value;
            }
        }

        public bool IsTable
        {
            get
            {
                return (whereClause == null || whereClause.Count == 0)
                    && (orderClause == null || orderClause.Count == 0);
            }
        }

        #endregion 存储查询表达式

        internal string Alias { get; set; }

        internal abstract void BuildSql(StringBuilder stringBuilder);

        internal abstract string MapField(MemberExpression memberAccess);

        internal abstract void BuildFieldList(StringBuilder stringBuilder);

        internal abstract void BuildFieldList(StringBuilder stringBuilder, Expression expression);

        internal abstract void BuildQueryList(StringBuilder stringBuilder);

        internal abstract void BuildCondition(StringBuilder stringBuilder);

        internal abstract void BuildOrder(StringBuilder stringBuilder);

        internal static void BuildSubQuery(StringBuilder stringBuilder, SelectableBase query)
        {
            if (query.IsTable)
                query.BuildQueryList(stringBuilder);
            else
            {
                stringBuilder.Append('(');
                query.BuildSql(stringBuilder);
                stringBuilder.Append(')');
                if (query.Alias != null)
                {
                    stringBuilder.Append(' ');
                    stringBuilder.Append(query.Alias);
                }
            }
        }

        internal static SelectableBase Create(Type type)
        {
            Type typeOfSelectable = typeof(Selectable<>).MakeGenericType(type);
            return (SelectableBase)Activator.CreateInstance(typeOfSelectable);
        }
    }
}
